package com.blyat.xsoft.kernel.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.cert.X509Certificate;
import java.util.*;

/**
 * @Auther: syh
 * @Date: 2020/8/17
 * @Description:
 */
public class HttpUtil {

    private static final Logger logger = LoggerFactory.getLogger(HttpUtil.class);

    public static Map<String, Object> post(String url, Map<String, Object> params) throws IOException {
        return post(url, params, Map.class);
    }

    public static <T> T post(String url, Map<String, Object> params, Class<T> clazz) throws IOException {
        return post(url, null, params, clazz);
    }

    public static <T> T post(String url, Map<String, String> headers, Map<String, Object> params, Class<T> clazz) throws IOException {
        return post(url, headers, params, clazz, 30000);
    }

    public static <T> T post(String url, Map<String, String> headers, Map<String, Object> params, Class<T> clazz, int socketTimeout) throws IOException {
        return post(url, headers, params, clazz, 6000, 10000, socketTimeout);
    }

    public static <T> T post(String url, Map<String, String> headers, Map<String, Object> params, Class<T> clazz,
                             int connectTimeout, int requestTimeout, int socketTimeout) throws IOException {
        logger.debug("create http post:" + url);
        HttpClient httpclient = HttpClients.createDefault();
        if (url.startsWith("https")) {
            httpclient = wrapClient(httpclient);
        }
        HttpPost httpPost = postForm(url, headers, params);
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectTimeout).setConnectionRequestTimeout(requestTimeout).setSocketTimeout(socketTimeout).build();
        httpPost.setConfig(requestConfig);
        if (clazz.isAssignableFrom(String.class)) {
            return (T) invoke(httpclient, httpPost);
        }
        return JSONObject.parseObject(invoke(httpclient, httpPost), clazz);
    }

    public static Map<String, Object> post(String url, String params) throws IOException {
        return post(url, null, params, Map.class);
    }

    public static <T> T post(String url, String params, Class<T> clazz) throws IOException {
        return post(url, null, params, clazz);
    }

    public static <T> T post(String url, Map<String, String> headers, String params, Class<T> clazz) throws IOException {
        return post(url, headers, params, clazz, 30000);
    }

    public static <T> T post(String url, Map<String, String> headers, String params, Class<T> clazz, int socketTimeout) throws IOException {
        return post(url, headers, params, clazz, 5000, 1000, socketTimeout);
    }

    public static <T> T post(String url, Map<String, String> headers, String jsonParam, Class<T> clazz,
                             int connectTimeout, int requestTimeout, int socketTimeout) throws IOException {
        logger.debug("create post request with json param");
        HttpClient httpclient = HttpClients.createDefault();
        if (url.startsWith("https")) {
            httpclient = wrapClient(httpclient);
        }
        HttpPost httpPost = postJson(url, headers, jsonParam);
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectTimeout)
                .setConnectionRequestTimeout(requestTimeout).setSocketTimeout(socketTimeout).build();
        httpPost.setConfig(requestConfig);
        if (clazz.isAssignableFrom(String.class)) {
            return (T)invoke(httpclient, httpPost);
        }
        return JSONObject.parseObject(invoke(httpclient, httpPost), clazz);
    }

    public static String get(String url) throws IOException {
        return get(url, 5000, 1000, 30000);
    }

    public static String get(String url, int connectTimeout, int requestTimeout, int socketTimeout) throws IOException {
        logger.debug("create http get:" + url);
        HttpClient httpclient = HttpClients.createDefault();
        if (url.startsWith("https")) {
            httpclient = wrapClient(httpclient);
        }
        HttpGet httpGet = new HttpGet(url);
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectTimeout).setConnectionRequestTimeout(requestTimeout).setSocketTimeout(socketTimeout).build();
        httpGet.setConfig(requestConfig);
        return invoke(httpclient, httpGet);
    }

    private static String invoke(HttpClient httpclient, HttpUriRequest httpUriRequest) throws IOException {
        HttpResponse response = httpclient.execute(httpUriRequest);
        String result = parseResponse(response);
        if (response instanceof CloseableHttpResponse) {
            ((CloseableHttpResponse) response).close();
        }
        return result;
    }

    private static String parseResponse(HttpResponse response) throws IOException {
        HttpEntity entity = response.getEntity();
        return EntityUtils.toString(entity);
    }

    private static HttpPost postForm(String url, Map<String, String> headers, Map<String, Object> params) {
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> nvps = new ArrayList();
        Set keySet;
        Iterator var6;
        String key;
        if (params != null) {
            keySet = params.keySet();
            var6 = keySet.iterator();

            while (var6.hasNext()) {
                key = (String) var6.next();
                nvps.add(new BasicNameValuePair(key, (String) params.get(key)));
            }
        }

        try {
            logger.debug("set utf-8 form entity to http post");
            httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
            logger.debug("set utf-8 form header to http post");
            if (headers != null) {
                keySet = headers.keySet();
                var6 = keySet.iterator();

                while (var6.hasNext()) {
                    key = (String) var6.next();
                    httpPost.addHeader(key, (String) headers.get(key));
                }
            }
        } catch (UnsupportedEncodingException var8) {
            logger.error("UnsupportedEncodingException", var8);
        }

        return httpPost;
    }

    private static HttpPost postJson(String url, Map<String, String> headers, String params) {

        HttpPost httpPost = new HttpPost(url);
        try {
            JSONObject.parseObject(params);
            StringEntity entity = new StringEntity((params), "application/json", "utf-8");
            httpPost.setEntity(entity);

            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue());
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return httpPost;
    }

    private static HttpClient wrapClient(HttpClient base) {
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] xcs, String string) {
                }

                public void checkServerTrusted(X509Certificate[] xcs, String string) {
                }

                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };
            ctx.init(null, new TrustManager[]{tm}, null);
            SSLSocketFactory ssf = new SSLSocketFactory(ctx);
            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = base.getConnectionManager();
            SchemeRegistry sr = ccm.getSchemeRegistry();
            sr.register(new Scheme("https", ssf, 443));
            return new DefaultHttpClient(ccm, base.getParams());
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }
}
